#include "CDisplayWidget.h"

#include <QDebug>
#include <QPainter>
#include <random>

CDisplayWidget::CDisplayWidget(QWidget *parent) : QWidget(parent)
{
    this->resize(1000, 1000);

    this->initWidget();

    this->setMouseTracking(false);

    m_size_x = this->size().width();
    m_size_y = this->size().height();

    qDebug("CDisplayWidget:[%d, %d]\n", m_size_x, m_size_y);

    m_init_timer = new QTimer;
    connect(m_init_timer, &QTimer::timeout, this, &CDisplayWidget::initTimerCallback);
    m_init_timer->setSingleShot(true);
    m_init_timer->start(100);

    m_tree_point_list.clear();

    m_mouse_event = MOUSE_EVENT_SET_OBSTACLE;
}

/**
 * @brief CDisplayWidget::initWidget
 * @note  初始化显示窗口
 */
void CDisplayWidget::initWidget()
{
    /* 设置白色背景 */
    QPalette palette(this->palette());
    palette.setColor(QPalette::Background, QColor(255, 255, 255));
    this->setAutoFillBackground(true);
    this->setPalette(palette);
}

void CDisplayWidget::paintGrid(QPainter &painter)
{
    painter.setPen(QPen(Qt::lightGray, 1));

    for (quint16 i = 0; i <= m_size_x; i += 50)
    {
        QPoint start(i, 0);
        QPoint end(i, m_size_y);
        painter.drawLine(start, end);
    }

    for (quint16 i = 0; i <= m_size_y; i += 50)
    {
        QPoint start(0, i);
        QPoint end(m_size_y, i);
        painter.drawLine(start, end);
    }
}

void CDisplayWidget::paintObstacle(QPainter &painter)
{
    painter.setPen(QPen(Qt::black, 1));
    for (const auto &each : m_obstacle_list)
    {
        painter.drawPoint(each);
    }
}

void CDisplayWidget::paintStartAndDestPoint(QPainter &painter)
{
    if (!m_start_point.isNull())
    {
        painter.setPen(QPen(Qt::blue, 10));
        painter.drawPoint(m_start_point);

        painter.setPen(QPen(Qt::red, 2));
        QRectF rectangle1(m_start_point.x() - 20.0, m_start_point.y() - 20.0, 40.0, 40.0);
        painter.drawEllipse(rectangle1);
    }

    if (!m_dest_point.isNull())
    {
        painter.setPen(QPen(Qt::green, 10));
        painter.drawPoint(m_dest_point);

        painter.setPen(QPen(Qt::red, 2));
        QRectF rectangle1(m_dest_point.x() - 20.0, m_dest_point.y() - 20.0, 40.0, 40.0);
        painter.drawEllipse(rectangle1);
    }
}

void CDisplayWidget::paintRandomNewPoint(QPainter &painter)
{
    if (!m_new_random_point.isNull())
    {
        painter.setPen(QPen(Qt::yellow, 10));
        painter.drawPoint(m_new_random_point);

//        painter.setPen(QPen(QColor(139, 90, 0), 2));
//        QRectF rectangle1(m_new_random_point.x() - 20.0, m_new_random_point.y() - 20.0, 40.0, 40.0);
//        painter.drawEllipse(rectangle1);
    }
}

void CDisplayWidget::paintTreePoint(QPainter &painter)
{
    if (m_tree_point_list.size() > 1)
    {
        for (int i = 0; i < m_tree_point_list.size(); i ++)
        {
            painter.setPen(QPen(QColor(193, 205, 193), 5));
            if (!m_tree_point_list.at(i).parent.isNull())
            {
                painter.drawLine(m_tree_point_list.at(i).point, m_tree_point_list.at(i).parent);
            }
        }
    }

    for (int i = 0; i < m_tree_point_list.size(); i ++)
    {
        painter.setPen(QPen(QColor(30, 144, 255), 10));
        painter.drawPoint(m_tree_point_list.at(i).point);
//        QRectF rectangle1(m_tree_point_list.at(i).point.x() - 20.0, m_tree_point_list.at(i).point.y() - 20.0, 40.0, 40.0);
    }
}

void CDisplayWidget::paintOriginPathPoint(QPainter &painter)
{
    for (int i = 0; i < m_origin_path.size() - 1; i ++)
    {
        painter.setPen(QPen(Qt::red, 2));
        painter.drawLine(m_origin_path.at(i), m_origin_path.at(i+1));
    }
}

void CDisplayWidget::paintCar(QPainter &painter)
{

}

void CDisplayWidget::slotInitMode(int mouse_event, int obstacle_size)
{
    m_mouse_event = (TMouseEvent)(mouse_event + 1);
    m_obstacle_expand_size = obstacle_size;

}

void CDisplayWidget::slotResetMap()
{
    m_start_point.setX(0);
    m_start_point.setY(0);

    m_dest_point.setX(0);
    m_dest_point.setY(0);

    m_new_random_point.setX(0);
    m_new_random_point.setY(0);

    m_obstacle_list.clear();
    m_tree_point_list.clear();
    m_origin_path.clear();
}

void CDisplayWidget::slotClearPath()
{
    //m_start_point.setX(0);
    //m_start_point.setY(0);

    //m_dest_point.setX(0);
    //m_dest_point.setY(0);

    m_new_random_point.setX(0);
    m_new_random_point.setY(0);

    m_tree_point_list.clear();
    m_origin_path.clear();
}

void CDisplayWidget::slotDisplayRandomPoint(QPoint point)
{
    m_new_random_point = point;
}

void CDisplayWidget::slotReceiveNewTreePoint(TNode new_node)
{
    m_tree_point_list.push_back(new_node);
}

void CDisplayWidget::slotReceiveOriginPath(QVector<QPoint> path)
{
    m_origin_path = path;
}

void CDisplayWidget::expandClickObstaclePoint(QPoint click_pos, QVector<QPoint> &point_list)
{
    for (int i = -m_obstacle_expand_size; i <= m_obstacle_expand_size; i ++)
    {
        for (int j = -m_obstacle_expand_size; j <= m_obstacle_expand_size; j ++)
        {
            int pos_x = click_pos.x() + i;
            int pos_y = click_pos.y() + j;

            if (pos_x < 0 || pos_y < 0 || pos_x > 1000 || pos_y > 1000)
            {
                continue;
            }

            QPoint extend_point;
            extend_point.setX(pos_x);
            extend_point.setY(pos_y);
            point_list.push_back(extend_point);
        }
    }
}

void CDisplayWidget::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    QPainter painter(this);

    paintGrid(painter);

    paintObstacle(painter);

    paintStartAndDestPoint(painter);

    paintTreePoint(painter);

    paintRandomNewPoint(painter);

    paintOriginPathPoint(painter);

    update();
}

void CDisplayWidget::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        qDebug("mousePressEvent -> LeftButton\n");

        QPointF click_pos = event->localPos();
        QPoint  pos = click_pos.toPoint();

        switch(m_mouse_event)
        {
        case MOUSE_EVENT_SET_OBSTACLE:
        {
            QVector<QPoint> obstacle_list;
            expandClickObstaclePoint(pos, obstacle_list);
            emit signalUpdateMapData(obstacle_list);

            for (auto &each : obstacle_list)
            {
                m_obstacle_list.push_back(each);
            }
            break;
        }
        case MOUSE_EVENT_SET_START_POINT:
        {
            m_start_point = pos;
            emit signalSetStartPoint(m_start_point);
            break;
        }
        case MOUSE_EVENT_SET_DEST_POINT:
        {
            m_dest_point = pos;
            emit signalSetDestPoint(m_dest_point);
            break;
        }
        default:break;
        }
    }
    else if (event->button() == Qt::RightButton)
    {
        qDebug("mousePressEvent -> RightButton\n");
    }
}

void CDisplayWidget::initTimerCallback()
{
    emit signalNotifyMapSize(this->size().height(), this->size().width());
}
